//
// MIME type/conversion database definitions for CUPS.
//
// Copyright © 2020-2024 by OpenPrinting.
// Copyright © 2007-2013 by Apple Inc.
// Copyright © 1997-2007 by Easy Software Products, all rights reserved.
//
// Licensed under Apache License v2.0.  See the file "LICENSE" for more
// information.
//

#ifndef _CUPS_MIME_H_
#  define _CUPS_MIME_H_
#  include <cups/array.h>
#  include <cups/ipp.h>
#  include <cups/file.h>
#  include <cups/thread.h>
#  include <regex.h>
#  ifdef __cplusplus
extern "C" {
#  endif // __cplusplus


//
// Constants...
//

#  define MIME_MAX_SUPER	16	// Maximum size of supertype name
#  define MIME_MAX_TYPE		IPP_MAX_NAME
					// Maximum size of type name
#  define MIME_MAX_FILTER	256	// Maximum size of filter pathname
#  define MIME_MAX_BUFFER	8192	// Maximum size of file buffer


//
// Types/structures...
//

typedef enum
{
  MIME_MAGIC_NOP,			// No operation
  MIME_MAGIC_AND,			// Logical AND of all children
  MIME_MAGIC_OR,			// Logical OR of all children
  MIME_MAGIC_MATCH,			// Filename match
  MIME_MAGIC_ASCII,			// ASCII characters in range
  MIME_MAGIC_PRINTABLE,			// Printable characters (32-255) in range
  MIME_MAGIC_STRING,			// String matches
  MIME_MAGIC_CHAR,			// Character/byte matches
  MIME_MAGIC_SHORT,			// Short/16-bit word matches
  MIME_MAGIC_INT,			// Integer/32-bit word matches
  MIME_MAGIC_LOCALE,			// Current locale matches string
  MIME_MAGIC_CONTAINS,			// File contains a string
  MIME_MAGIC_ISTRING,			// Case-insensitive string matches
  MIME_MAGIC_REGEX			// Regular expression matches
} mime_op_t;

typedef struct _mime_magic_s		// MIME Magic Data
{
  struct _mime_magic_s	*prev,		// Previous rule
			*next,		// Next rule
			*parent,	// Parent rules
			*child;		// Child rules
  short		op,			// Operation code (see above)
		invert;			// Invert the result
  int		offset,			// Offset in file
		region,			// Region length
		length;			// Length of data
  union
  {
    char	matchv[64];		// Match value
    char	localev[64];		// Locale value
    char	stringv[64];		// String value
    unsigned char charv;		// Byte value
    unsigned short shortv;		// Short value
    unsigned	intv;			// Integer value
    regex_t	rev;			// Regular expression value
  }		value;
} mime_magic_t;

typedef struct _mime_type_s		// MIME Type Data
{
  mime_magic_t	*rules;			// Rules used to detect this type
  int		priority;		// Priority of this type
  char		super[MIME_MAX_SUPER],	// Super-type name ("image", "application", etc.)
		type[MIME_MAX_TYPE];	// Type name ("png", "postscript", etc.)
} mime_type_t;

typedef struct _mime_filter_s		// MIME Conversion Filter Data
{
  mime_type_t	*src,			// Source type
		*dst;			// Destination type
  int		cost;			// Relative cost
  char		filter[MIME_MAX_FILTER];// Filter program to use
  size_t	maxsize;		// Maximum file size for this filter
} mime_filter_t;

typedef void (*mime_error_cb_t)(void *ctx, const char *message);

typedef struct _mime_s			// MIME Database
{
  cups_array_t		*types;		// File types
  cups_array_t		*filters;	// Type conversion filters
  cups_array_t		*srcs;		// Filters sorted by source type
  mime_error_cb_t	error_cb;	// Error message callback
  void			*error_ctx;	// Pointer for callback
  cups_rwlock_t		lock;		// Read/write lock for guarding data for background updates
} mime_t;


//
// Functions...
//

extern mime_filter_t	*mimeAddFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst, int cost, const char *filter);
extern mime_type_t	*mimeAddType(mime_t *mime, const char *super, const char *type);
extern int		mimeAddTypeRule(mime_type_t *mt, const char *rule);

extern void		mimeDelete(mime_t *mime);
extern void		mimeDeleteFilter(mime_t *mime, mime_filter_t *filter);
extern void		mimeDeleteType(mime_t *mime, mime_type_t *mt);

extern mime_type_t	*mimeFileType(mime_t *mime, const char *pathname, const char *filename, int *compression);
extern cups_array_t	*mimeFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst, int *cost);
extern cups_array_t	*mimeFilter2(mime_t *mime, mime_type_t *src, size_t srcsize, mime_type_t *dst, int *cost);
extern mime_filter_t	*mimeFilterLookup(mime_t *mime, mime_type_t *src, mime_type_t *dst);
extern mime_filter_t	*mimeFirstFilter(mime_t *mime);
extern mime_type_t	*mimeFirstType(mime_t *mime);

extern mime_t		*mimeLoad(const char *pathname, const char *filterpath);
extern mime_t		*mimeLoadFilters(mime_t *mime, const char *pathname, const char *filterpath);
extern mime_t		*mimeLoadTypes(mime_t *mime, const char *pathname);

extern mime_t		*mimeNew(void);
extern mime_filter_t	*mimeNextFilter(mime_t *mime);
extern mime_type_t	*mimeNextType(mime_t *mime);
extern int		mimeNumFilters(mime_t *mime);
extern int		mimeNumTypes(mime_t *mime);

extern void		mimeSetErrorCallback(mime_t *mime, mime_error_cb_t cb, void *context);

extern mime_type_t	*mimeType(mime_t *mime, const char *super, const char *type);


#  ifdef __cplusplus
}
#  endif // __cplusplus
#endif // !_CUPS_MIME_H_
